//
//  WDFileCache.swift
//  WDLogicBehind
//
//  Created by Alean on 2022/12/14.
//

import UIKit
import UIKitExtentions

@objcMembers
public class WDFileCache: NSObject {
    
//    private class func cacheDirectory(type: WDFileType, directory: FileManager.SearchPathDirectory) -> String {
//        let paths = NSSearchPathForDirectoriesInDomains(directory, FileManager.SearchPathDomainMask.userDomainMask, true)
//        let path = paths[0].appending("/").appending("\(type.folderName)")
//        if !FileManager.default.fileExists(atPath: path) {
//            try? FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
//        }
//        return path
//    }

    /// 根据远端url生成本地缓存地址
    /// - Parameters:
    ///   - remoteURL: 远端url
    ///   - type: 缓存类型
    ///   - directory: cache 或者 document
    /// - Returns: 有即为本地url
    public class func fileLocalURL(remoteURL: URL, type: WDFileType) -> URL? {
        let pathExtension = ".\(remoteURL.pathExtension)"
        do {
            let fileURLString = try WDHelper.cacheDirectory(type: type).appending("/").appending(remoteURL.absoluteString.wd.md5).appending(pathExtension)
            return URL(fileURLWithPath: fileURLString)
        } catch let error {
            WDLog(error.localizedDescription, .error)
        }
        return nil
    }

    /// 根据远端url查看本地是否有该文件
    /// - Parameters:
    ///   - url: 远端url
    ///   - type: 缓存地址
    ///   - directory: cache 或者 document
    /// - Returns: 有即为本地url
    public class func fileHasLoaded(url: URL, type: WDFileType) -> URL? {
        if url.isFileURL {
            if FileManager.default.fileExists(atPath: url.path) {
                return url
            }
        }
        if FileManager.default.fileExists(atPath: url.path) {
            return url
        }
        if let cacheURL = fileLocalURL(remoteURL: url, type: type),
           FileManager.default.fileExists(atPath: cacheURL.path) {
            return cacheURL
        }
        return nil
    }
    
    /// 清除文件或文件夹
    /// - Parameters:
    ///   - type: 缓存类型
    ///   - directory: cache 或者 document
    public class func clearFileOnDisk(type: WDFileType) {
        guard let fileURLString = try? WDHelper.cacheDirectory(type: type) else { return }
        try? FileManager.default.removeItem(at: URL(fileURLWithPath: fileURLString, isDirectory: true))
        try? WDHelper.cacheDirectory(type: type)
    }
    
    /// 清除缓存
    /// - Parameters:
    ///   - type: 缓存类型
    ///   - directory: cache 或者 document
    ///   - onlyUserCache: 是否只清理工程创建的 默认是
    public class func removeCached(type: WDFileType, directory: FileManager.SearchPathDirectory? = nil, onlyUserCache: Bool = true) {
        assert(!(type == .allFile && directory == nil), "WDFileType 为 .allFile 时，directory 不能为nil")
        var directoryType = directory
        if directoryType == nil {
            directoryType = type.directory
        }

        if let filePath = try? WDHelper.cacheDirectory(type: type, directory: directoryType!) {
            let diskCacheURL = URL(fileURLWithPath: filePath)
            let resourceKeys: Set<URLResourceKey> = [.isDirectoryKey, .contentAccessDateKey, .totalFileAllocatedSizeKey]
            for fileUrl in (try? FileManager.default.contentsOfDirectory(at: diskCacheURL, includingPropertiesForKeys: Array(resourceKeys), options: .skipsHiddenFiles)) ?? [] {
                do {
//                    if fileUrl.pathExtension != type.folderName && type != .allFile {
//                        continue
//                    }

                    var isCanRemove = true
                    if onlyUserCache {
                        let resourceValues = try fileUrl.resourceValues(forKeys: resourceKeys)
                        if resourceValues.isDirectory == true {
                            isCanRemove = isUserFolder(fileUrl: fileUrl)
                        }
                    }
                    if isCanRemove {
                        try FileManager.default.removeItem(at: fileUrl)
                    }
                } catch let error {
                    WDLog(error.localizedDescription, .error)
                }
            }
        }
    }
    
    /// 获取缓存大小
    /// - Parameters:
    ///   - type: 缓存类型
    ///   - directory: cache 或者 document
    ///   - onlyUserCache: 是否只清理工程创建的 默认是true
    /// - Returns: 大小byte
    public class func travelCachedSize(type: WDFileType, directory: FileManager.SearchPathDirectory? = nil, onlyUserCache: Bool = true) -> UInt {
        var diskCacheSize: UInt = 0
        var directoryType = directory
        if directoryType == nil {
            directoryType = type.directory
        }
        
        if let filePath = try? WDHelper.cacheDirectory(type: type, directory: directoryType!) {
            let diskCacheURL = URL(fileURLWithPath: filePath)
            let resourceKeys: Set<URLResourceKey> = [.isDirectoryKey, .contentAccessDateKey, .totalFileAllocatedSizeKey]

            for fileUrl in (try? FileManager.default.contentsOfDirectory(at: diskCacheURL, includingPropertiesForKeys: Array(resourceKeys), options: .skipsHiddenFiles)) ?? [] {
                do {
                    print("fileUrl = \(fileUrl) \(fileUrl.pathExtension) \(fileUrl.lastPathComponent)")
//                    if fileUrl.pathExtension != type.folderName && type != .allFile {
//                        continue
//                    }
                    let resourceValues = try fileUrl.resourceValues(forKeys: resourceKeys)
                    // If it is a Directory. Continue to next file URL.
                    if resourceValues.isDirectory == true {
                        var isUserFold = isUserFolder(fileUrl: fileUrl)
                        if onlyUserCache, !isUserFold {
                            continue
                        }
                        diskCacheSize += folderSize(folderPath: fileUrl.path)
                    } else {
                        diskCacheSize += fileSize(filePath: fileUrl.path)
//                        if let fileSize = resourceValues.totalFileAllocatedSize {
//                            diskCacheSize += UInt(fileSize)
//                        }
                    }
                } catch let error {
                    WDLog(error.localizedDescription, .error)
                }
            }
        }
        return diskCacheSize
    }
}

extension WDFileCache {
    private class func isUserFolder(fileUrl: URL) -> Bool {
        var isUserFolder = false

        for userType in WDFileType.allCases {
            if userType == .dbFile || userType == .allFile {
                continue
            }
            if fileUrl.lastPathComponent == userType.folderName {
                print("userType = \(userType.folderName)")
                isUserFolder = true
                break
            }
        }
        return isUserFolder
    }

    private class func folderSize(folderPath: String) -> UInt {
        let manager = FileManager.default
        var size: UInt = 0
        if manager.fileExists(atPath: folderPath) {
            if let childFilesEnumerator = manager.subpaths(atPath: folderPath) {
                for (index, value) in childFilesEnumerator.enumerated() {
                    let fileAbsolutePath = folderPath + "/\(value)"
                    size += fileSize(filePath: fileAbsolutePath)
                }
            }
        }
        return size
    }
    
    private class func fileSize(filePath: String) -> UInt {
        let manager = FileManager.default
        var size: UInt = 0
        if manager.fileExists(atPath: filePath) {
            do {
                let fileAttributes = try manager.attributesOfItem(atPath: filePath)
                
//                if let isDirectory = fileAttributes[FileAttributeKey.type] as? FileAttributeType {
//                    if isDirectory == FileAttributeType.typeDirectory {
//                        size = folderSize(folderPath: filePath)
//                        print("Folder Size: \(size) \(filePath)")
//                    } else if let fileSize = fileAttributes[FileAttributeKey.size] as? NSNumber {
//                        print("File Size: \(fileSize.uint32Value) \(filePath)")
//                        size = fileSize.uintValue
//                    }
//                }
                
                if let fileSize = fileAttributes[FileAttributeKey.size] as? NSNumber {
                    print("File Size: \(fileSize.uint32Value) \(filePath)")
                    size = fileSize.uintValue
                }
//                if let ownerName = fileAttributes[FileAttributeKey.ownerAccountName] {
//                    print("File Owner: \(ownerName)")
//                }
//
//                //获取本地时区及与GMT的时间间隔
//                let timeZone = NSTimeZone.system
//                let interval = TimeInterval(timeZone.secondsFromGMT())
//
//                if let creationDate = fileAttributes[FileAttributeKey.creationDate] as? NSDate {
//                    let localCreateDate = creationDate.addingTimeInterval(interval)
//                    print("File Creation Date: \(localCreateDate)")
//                }
//
//                if let modificationDate = fileAttributes[FileAttributeKey.modificationDate] as? NSDate {
//                    let localModDate = modificationDate.addingTimeInterval(interval)
//                    print("File Modification Date: \(localModDate)")
//                }
            } catch let error as NSError {
                print("Get attributes errer: \(error)")
            }
        }
        return size
    }

}
